package gae.testjig.server;

import com.google.appengine.api.memcache.Expiration;
import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;

// altered form of http://blog.listry.com/2010/05/app-engine-locking-with-memcache.html

public class MemcacheSemaphore {
	
	static private String ABORT = "ABORT";
	static private String ADVANCE = "ADVANCE";

	private String signalKey;
	private String underwayKey;
	private int pollPeriodMilliseconds;

	public MemcacheSemaphore(String key) {
		int pollPeriodSeconds = 1; // just control this value here, not as arg
		this.signalKey = "mc_semaphore." + key;
		this.underwayKey = "mc_semaphore_underway." + key;
		this.pollPeriodMilliseconds = pollPeriodSeconds * 1000;
	}

	
	public boolean abort() {
		return signal(ABORT);
	}

	public boolean advance() {
		return signal(ADVANCE);
	}

	private boolean signal(String action) {
		MemcacheService mc = MemcacheServiceFactory.getMemcacheService();
		boolean success = mc.put(signalKey, action, Expiration.byDeltaMillis(pollPeriodMilliseconds*2), MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT);
		return success;
	}
	
	public void setUnderway(boolean isUnderway) {
		MemcacheService mc = MemcacheServiceFactory.getMemcacheService();
		if ( isUnderway ) {
			mc.put(underwayKey, "UNDERWAY", Expiration.byDeltaSeconds(12*60), MemcacheService.SetPolicy.ADD_ONLY_IF_NOT_PRESENT);
		} else {
			mc.delete(underwayKey);
		}
	}
	
	public boolean isUnderway() {
		if ( null != MemcacheServiceFactory.getMemcacheService().get(underwayKey) ) {
			return true;
		}
		return false;
	}
	

	public void poll() throws AbortException {
		String action = readAction();
		while ( null == action ) {
			try { Thread.sleep(pollPeriodMilliseconds); } catch (InterruptedException e) {}
			action = readAction();
		}
	}

	private String readAction() throws AbortException {
		String action = (String) MemcacheServiceFactory.getMemcacheService().get(signalKey);
		MemcacheServiceFactory.getMemcacheService().delete(signalKey); // can safely delete correct one because the put will only put if none exists.
		if ( ABORT.equals(action) ) {
			throw new AbortException();
		}
		return action;
	}

}